#include <iostream>
#include <string>
#include <conio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define PORT 110
#define SINA "pop.sina.com.cn"
#define QQ   "pop.qq.com"
#define W163 "pop.163.com"
#define W126 "pop.126.com"
using namespace::std;
SOCKET clsock;
char pop3name[20];
char buf[1000];
void recvinfo();
void pop3_list();
void pop3_retr();
void pop3_uidl();
void pop3_dele();
bool pop3_quit();
int POW(int a,int b);
int main()
{
	//创建套接字
	WSAData wsadata;
	WSAStartup(WINSOCK_VERSION,&wsadata);
	clsock=socket(AF_INET,SOCK_STREAM,0);
	if(clsock==INVALID_SOCKET)
	{
		WSACleanup();
		return -1;
	}
 
	//选择邮箱
	int num;
	memset(pop3name,0,20);
	cout<<"***************选择邮箱******************"<<endl;
	cout<<"请选择邮箱:"<<endl;
	cout<<"新浪--1  QQ--2  网易163--3   网易126--4"<<endl;
    cout<<"******************************************"<<endl;
	cin>>num;
	switch(num)
	{
	case 1:memcpy(pop3name,SINA,sizeof(SINA));
		   break;
	case 2:memcpy(pop3name,QQ,sizeof(QQ));
		   break;
	case 3:memcpy(pop3name,W163,sizeof(W163));
		   break;
    case 4:memcpy(pop3name,W126,sizeof(W126));
		   break;
	}
 
	//连接至服务器
	struct sockaddr_in pop3server;
	hostent *hostinfo;
	hostinfo=gethostbyname(pop3name);
	memset(&pop3server,0,sizeof(sockaddr_in));
	pop3server.sin_family=AF_INET;
	pop3server.sin_port=htons(PORT);
	memcpy(&pop3server.sin_addr.S_un.S_addr,hostinfo->h_addr_list[0],hostinfo->h_length);
 
    if(connect(clsock,(struct sockaddr *)&pop3server,sizeof(sockaddr_in))==SOCKET_ERROR)
	{
		cout<<"error:"<<WSAGetLastError()<<endl;
	}
 
	recvinfo();
	cout<<"**************连接至服务器*******************"<<endl;
	cout<<"connect info:"<<endl<<buf<<endl;
	cout<<"*********************************************"<<endl;
 
    //认证
	send(clsock,"AUTH\r\n",strlen("AUTH\r\n"),0);
	recvinfo();
    cout<<"**************认证信息**********************"<<endl;
	cout<<"auth info:"<<endl<<buf<<endl;
	cout<<"*********************************************"<<endl;
 
	//发送用户名及密码
	cout<<"**************发送用户名*******************"<<endl;
	char sendbuf[30]="USER ";
	cout<<"请输入用户名："<<endl;
	char username[20];
	cin>>username;
	int len=strlen(username);
	username[len]='\r';
	username[len+1]='\n';
	memcpy(sendbuf+5,username,len+2);
	send(clsock,sendbuf,strlen(sendbuf),0);
	recvinfo();
	cout<<"Reply: "<<endl<<buf<<endl;
	cout<<"*********************************************"<<endl;
    cout<<"**************发送密码***********************"<<endl;
	memset(sendbuf,0,30);
	memcpy(sendbuf,"PASS ",strlen("PASS "));
	cout<<"请输入密码："<<endl;
	char psw[20];
	cin>>psw;
	len=strlen(psw);
	psw[len]='\r';
	psw[len+1]='\n';
	memcpy(sendbuf+5,psw,len+2);
	send(clsock,sendbuf,strlen(sendbuf),0);
	recvinfo();
	cout<<"Reply: "<<endl<<buf<<endl;
	cout<<"*********************************************"<<endl;
 
	cout<<"******************STAT***************************"<<endl;
    send(clsock,"STAT\r\n",strlen("STAT\r\n"),0);
	recvinfo();
	cout<<"Reply: "<<endl<<buf<<endl;
	cout<<"*********************************************"<<endl;
 
	//进入处理状态，选择执行命令
	int flag=0;
	while(1)
	{
		cout<<"**************选择执行命令： ***********"<<endl;
		cout<<"查询邮件大小--1 查询邮件标示--2 查询邮件内容--3 删除--4 退出--5"<<endl;
		int num;
		cin>>num;
		switch(num)
		{
		case 1:pop3_list();
			break;
		case 2:pop3_uidl();
			break;
		case 3:pop3_retr();
			break;
		case 4:pop3_dele();
			break;
		case 5:if(pop3_quit())  flag=1;
			break;
		}
		if(flag==1)  break;
	}
 
	system("pause");
	return 0;
}
void recvinfo()
{
	memset(buf,0,1000);
	recv(clsock,buf,1000,0);
}
void pop3_list()
{
	cout<<"**************查询邮件大小*******************"<<endl;
	cout<<"查询全部？--y[YES],n[NO]"<<endl;
	char s;
	cin>>s;
	if(s=='y')
	{
		send(clsock,"LIST\r\n",strlen("LIST\r\n"),0);
		cout<<"全部邮件大小如下："<<endl;
		recvinfo();
		cout<<buf<<endl;
	}
	else
	{
		cout<<"请输入邮件序号："<<endl;
		char num[3];
		cin>>num;
		char sendbuf[20]="LIST ";
		memcpy(sendbuf+5,num,strlen(num));
	    int len=strlen(sendbuf);
	    sendbuf[len]='\r';
	    sendbuf[len+1]='\n';
		send(clsock,sendbuf,strlen(sendbuf),0);
		recvinfo();
		cout<<"第"<<num<<"邮件大小为："<<endl;
		cout<<buf<<endl;
	}
	cout<<"**********************************************"<<endl;
	return ;
}
void pop3_uidl()
{
    cout<<"**************查询邮件标示*******************"<<endl;
	cout<<"查询全部？--y[YES],n[NO]"<<endl;
	char s;
	cin>>s;
	if(s=='y')
	{
		send(clsock,"UIDL\r\n",strlen("UIDL\r\n"),0);
		cout<<"全部邮件标示如下："<<endl;
		recvinfo();
		cout<<buf<<endl;
	}
	else
	{
		cout<<"请输入邮件序号："<<endl;
		char num[3];
		cin>>num;
		char sendbuf[20]="UIDL ";
		memcpy(sendbuf+5,num,strlen(num));
	    int len=strlen(sendbuf);
	    sendbuf[len]='\r';
	    sendbuf[len+1]='\n';
		send(clsock,sendbuf,strlen(sendbuf),0);
		recvinfo();
		cout<<"第"<<num<<"邮件标示为："<<endl;
		cout<<buf<<endl;
	}
	cout<<"**********************************************"<<endl;
	return ;
}
void pop3_retr()
{
	cout<<"**************查询邮件内容*******************"<<endl;
    cout<<"请输入邮件序号："<<endl;
	char num[3];
    cin>>num;
	cout<<"请输入邮件保存路径:"<<endl;
	char path[20];
	cin>>path;
	char sendbuf[20]="RETR ";
	memcpy(sendbuf+5,num,strlen(num));
	int len=strlen(sendbuf);
	sendbuf[len]='\r';
	sendbuf[len+1]='\n';
	send(clsock,sendbuf,strlen(sendbuf),0);
	recvinfo();
	cout<<buf<<endl;
	
	int length=0;
	int i;
	for(i=0;buf[i]!=' ';i++);
	int j;
	for(j=i+1;buf[j]!=' ';j++);
	int k=j-1;
    for(j=k;j>i;j--)
       length+=(buf[j]-'0')*POW(10,k-j);
	cout<<length<<endl;
	FILE *fp;
	fp=fopen(path,"wb");
	if(fp==NULL)
	{
		cerr<<"error;"<<endl;
	}
	int L=0;
	while(1)
	{
		char buf[1025];
		memset(buf,0,1025);
		int num=recv(clsock,buf,1024,0);
		fwrite(buf,strlen(buf),1,fp);
		//cout<<buf<<endl;
		L+=num;
		if(L>=length)
		  break;
	}
	cout<<"**********************************************"<<endl;
	return ;
}
bool pop3_quit()
{
	cout<<"******************退出***********************"<<endl;
	cout<<"退出？y[YES],n[NO]"<<endl;
	char s;
	cin>>s;
	if(s=='y')
	{
		send(clsock,"QUIT\r\n",strlen("QUIT\r\n"),0);
	    recvinfo();
	    cout<<"Reply: "<<endl<<buf<<endl;
		cout<<"*********************************************"<<endl;
		return true;
	}
	else
	{
		cout<<"*********************************************"<<endl;
		return false;
	}
}
void pop3_dele()
{
   cout<<"******************删除***********************"<<endl;
   cout<<"请输入邮件序号:"<<endl;
   char num[3];
   cin>>num;
   cout<<"确认删除第"<<num<<"封邮件？y[YES],n[NO]"<<endl;
   char s;
   cin>>s;
   if(s=='y')
   {
       char sendbuf[20]="DELE ";
	   memcpy(sendbuf+5,num,strlen(num));
	   int len=strlen(sendbuf);
	   sendbuf[len]='\r';
	   sendbuf[len+1]='\n';
	   send(clsock,sendbuf,strlen(sendbuf),0);
	   recvinfo();
	   cout<<buf<<endl;
	   cout<<"已删除"<<endl;
	   send(clsock,"QUIT\r\n",strlen("QUIT\r\n"),0);
	   recvinfo();
	   cout<<"更新："<<buf<<endl;
   }
   cout<<"*********************************************"<<endl;
   return ;
}
int POW(int a,int b)
{
	int num=1;
	if(b==0)  return num;
	for(int i=0;i<b;i++)
		num*=a;
	return num;
}